上回提到使用 RGB 圖像做相機姿態估計或 3D 重建時,由於失去了相機與圖片中物體的真實距離,導致有尺度缺失的問題,因此無法得知物體的真實大小。
為了解決這個問題,我們可以引入額外的資訊,例如深度圖 (Depth Map)來幫助相機姿態估計或 3D 重建。
深度圖指的是一種類似 RGB 圖片的資料,但是每個像素點不再是顏色,而是該像素點到相機的真實距離,例如 1 公尺、2 公尺等等。不同於 RGB 圖片有 3 個 channel (R, G, B),深度圖只有一個 channel,代表的是深度值。
我們一直以來使用的 TUM RGB-D Dataset 就有提供深度圖(RGB-D 的意思就是 RGB + Depth 的意思),以下是深度圖的範例:
# 16-bit png 要用 cv2.IMREAD_UNCHANGED 讀取
depth = cv2.imread(frame["depth_path"], cv2.IMREAD_UNCHANGED)
# 轉換成 float32,真實世界的 1 公尺 = 5000 單位
depth = depth.astype(np.float32) / 5000.0
# 顯示深度圖
plt.imshow(depth)
plt.colorbar()
由於深度圖每個像素儲存的是距離(通常以公尺為單位)是個正的實數,不像 RGB 圖片是以 0-255 的整數儲存,沒辦法直接存成一個圖片,因此儲存時一般來說都是會乘上一個數字然後捨去小數點,才可以存成整數的圖片。例如以常見的數字為 1000 來說,真實世界的 1.3278 公尺就會變成 1327 單位,10 公尺就會變成 10000 單位等。
儲存可以使用 16-bit 的 png 格式,也就是說每個像素點可以儲存最高 2^16 = 65536 的單位深度。因此儲存的乘數越大,代表深度值的精度越高(捨去的小數點越少),但儲存的深度上限也會越小。
讀者在讀取數據集的深度圖時要注意它是以什麼樣的單位儲存的,例如,在 TUM RGB-D 數據集中,這個數字是 5000,因此我們在讀取時要除以 5000,才會得到真實的深度值(以公尺為單位)。
當然也有一些別的儲存格式,例如使用 32-bit 的浮點數,這樣就可以儲存真實的深度值,但是這樣的圖片檔案會比較大,佔用空間,不過在一些應用中可能會需要這樣的精度,如 exr 或是 tiff 等格式可以儲存較高精度的深度值。
值得一提的是,使用 png 格式儲存是因為 png 是無損壓縮的格式,比起 jpg 格式,這樣可以確保深度值不會因為壓縮而失真。
另外,值得注意的是,通常深度圖由於取得的方式不同(下一篇會討論),會有一些像素沒有深度值,這時候我們可以用一個特定的數字(例如 0)來代表沒有深度值,上面的範例中背景深藍色就是沒有深度值的部分。由於不同的數據集可能會有不同的表示方法,這個數字也是實作時要特別注意的。